use serde::{Deserialize, Serialize};
use pyo3::prelude::*;
use crate::DataTransferObject;
use crate::order::Direction;
use crate::currency::Currency;

#[pyclass]
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct Authority {
    #[pyo3(get, set)]
    pub client_id: Option<u64>, // 用户ID(哈希, 可通过该标识重新连接)
}

impl DataTransferObject for Authority {
    // Derive
}

#[pymethods]
impl Authority {
    #[new]
    pub fn new(client_id: Option<u64>) -> Self {
        Authority { client_id }
    }

    fn __repr__(&self) -> String {
        format!("Auth(uid={:?})", self.client_id)
    }
}

#[pyclass]
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct Position {
    #[pyo3(get, set)]
    pub symbol: String,    // 品种
    #[pyo3(get, set)]
    pub side: Direction,   // 方向 (多/空)
    #[pyo3(get, set)]
    pub cost: f64,         // 平均价格(成本)
    #[pyo3(get, set)]
    pub quantity: u64,     // 数量
    #[pyo3(get, set)]
    pub liquidatable: u64, // 可平仓数量
    #[pyo3(get, set)]
    pub opening: u64,      // 正挂单数量
    #[pyo3(get, set)]
    pub multiple: u32,     // 合约乘数
}

impl DataTransferObject for Position {
    // Derive
}

#[pymethods]
impl Position {
    #[new]
    pub fn new(
        symbol: String,
        side: Direction,
        cost: f64,
        quantity: u64,
        liquidatable: u64,
        opening: u64,
    ) -> Self {
        Position {
            symbol,
            side,
            cost,
            quantity,
            liquidatable,
            opening,
            multiple: 1,
        }
    }

    fn __repr__(&self) -> String {
        format!("Position(symbol={}, side={:?}, cost={}, quantity={}, liquidatable={}, working={}, multiple={})",
                self.symbol, self.side, self.cost, self.quantity, self.liquidatable, self.opening, self.multiple)
    }
}

#[pyclass]
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct Portfolio {
    #[pyo3(get, set)]
    pub client_id: u64, // 用户ID(哈希, 可通过该标识重新连接)
    #[pyo3(get, set)]
    pub positions: Vec<Position>, // 持仓列表
    #[pyo3(get, set)]
    pub balance: i64,        // 账户余额(单位: 分)
    #[pyo3(get, set)]
    pub balance_available: i64,   // 可用余额(单位: 分)
    #[pyo3(get, set)]
    pub currency: Currency,       // 账户结算货币
}

impl DataTransferObject for Portfolio {
    // Derive
}

#[pymethods]
impl Portfolio {
    #[new]
    pub fn new(
        client_id: u64,
        positions: Vec<Position>,
        balance: i64,
        balance_available: i64,
    ) -> Self {
        Portfolio {
            client_id,
            positions,
            balance,
            balance_available,
            currency: Currency::CNY, // 默认人民币
        }
    }

    fn __repr__(&self) -> String {
        format!("Portfolio(client_id={}, positions_count={}, balance={}, balance_available={}, currency={:?})",
                self.client_id, self.positions.len(), self.balance, self.balance_available, self.currency)
    }
}